package com.example.emos.wx.controller;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.example.emos.wx.common.util.R;
import com.example.emos.wx.config.SystemConstants_系统常量数据;
import com.example.emos.wx.config.shiro.JwtUtil_根据ID生成_解密获ID_验证TOKEN;
import com.example.emos.wx.controller.form.CheckinForm;
import com.example.emos.wx.controller.form.SearchMonthCheckinForm;
import com.example.emos.wx.exception.EmosException;
import com.example.emos.wx.service.CheckinService;
import com.example.emos.wx.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * @ClassName : CheckinController
 * @Author : 骆发茂
 * @Date: 2021/10/20 23:09
 * @Description :
 */
@RestController//前端以json格式传给后端
@Api("签到模块web接口")
@Slf4j
@RequestMapping("/checkin")
public class CheckinController {

    @Autowired
    private CheckinService checkinService;

    @Value("${emos.image-folder}")
    private String imageFolder;

    //jwtutil工具类，从请求头中获取到userid；public String validCanCheckin(int userId,String data);
    @Autowired
    private JwtUtil_根据ID生成_解密获ID_验证TOKEN jwtUtil生成解密验证TOKEN;

    @Autowired
    private UserService userService;

    private SystemConstants_系统常量数据 systemConstants;

    @GetMapping("validCanCheckin")
    @ApiOperation("查看用户今天是否可以签到")
    public R validCanCheckin(@RequestHeader("token") /**把请求头里面的token放到token中*/String token) {
        int userId = jwtUtil生成解密验证TOKEN.getUserId(token);
        String result = checkinService.validCanCheckin(userId, DateUtil.today());
        return R.ok(result);
    }

  /** 7-12 实现人脸签到（Web层）
   * 签到的时候验证签到确定需要关注三部分->时间\人脸\地区风险*/
    @PostMapping("/checkin")
    @ApiOperation("签到")
    /**@Valid CheckinForm form  表单里面存的是地理信息
     * @RequestParam("photo") MultipartFile file  接收文件；从请求中的photo这个参数里面取内容；*/
    public R checkin(@Valid CheckinForm form, @RequestParam("photo") MultipartFile file,
                     @RequestHeader("token") String token) throws IOException {
        if (file == null) {
            return R.error("没有上传文件");

        }
        //根据token，jwtutil解析token找到userid
        int userId = jwtUtil生成解密验证TOKEN.getUserId(token);
        String fileName = file.getOriginalFilename().toLowerCase();
        if (!fileName.endsWith(".jpg")) {
                return R.error("必须提交jpg格式的图片");
            } else {
                String path = imageFolder + "/" + fileName;
                try {
                    //将数据传到数据库中，form表单
                    file.transferTo(Paths.get(path));
                    /**向HashMap里面存放信息，封装之后交给service去执行具体的内容*/
                    HashMap param = new HashMap();
                    param.put("userId", userId);
                    param.put("path", path);
                    param.put("city", form.getCity());
                    param.put("district", form.getDistrict());
                    param.put("address", form.getAddress());
                    param.put("country", form.getCountry());
                param.put("province", form.getProvince());
                checkinService.checkin(param);
                return R.ok("签到成功");
            } catch (IOException e) {
                log.error(e.getMessage(), e);
                throw new EmosException("图片保存错误");
            }
            /**签到成功之后，删除文件,本地库不保留*/
            finally {
                FileUtil.del(path);
            }
        }

    }


    /**异常情况下，没有人脸模型，就创建人脸模型*/
    @PostMapping("/createFaceModel")
    @ApiOperation("创建人脸模型")
    public R createFaceModel (@RequestParam("photo") MultipartFile file, @RequestHeader("token") String token){
        if(file==null){
            return R.error("没有上传文件");
        }
        int userId= jwtUtil生成解密验证TOKEN.getUserId(token);
        String fileName=file.getOriginalFilename().toLowerCase();
        if(!fileName.endsWith(".jpg")){
            return R.error("必须提交JPG格式图片");
        }
        else{
            //path是本地中的照片（照片地址的绝对路径）
            String path=imageFolder+"/"+fileName;
            try{
                file.transferTo(Paths.get(path));
                checkinService.createFaceModel(userId,path);
                return R.ok("人脸建模成功");
            }catch (IOException e){
                log.error(e.getMessage(),e);
                throw new EmosException("图片保存错误");
            }
            finally {
                FileUtil.del(path);
            }

        }
    }


    /**8-7实现考勤成功页面（业务层）(22-03)
     * 前端要显示：累计签到数、一周的考勤情况（缺勤迟到正常）
     * 后端首先要出意入职日期VS一周开始的日期；再塞入累计签到数、一周的考勤情况（缺勤迟到正常）
     * @param token，用户的token，不可能直接传USERID过来，只能通过token间接的获取userid
     * @return 返回R。签到的情况R有hashmap里面的信息
     */
    /**服务器是需要get（接收数据），所以就GetMapping？？？？？*/
    @GetMapping("/searchTodayCheckin")
    @ApiOperation("查询用户当日签到数据")
    public R searchTodayCheckin(@RequestHeader("token") String token){
        int userId=jwtUtil生成解密验证TOKEN.getUserId(token);
        //放进map入职日期
        HashMap map = checkinService.searchTodayCheckin(userId);
        //放进map开始的时间、结束的时间
        map.put("attendanceTime", systemConstants.attendanceTime);
        map.put("closingTime", systemConstants.closingTime);
        /** 根据userid的所有签到日期*/
        //放进map累计所有签到的数
        long days = checkinService.searchCheckinDays(userId);
        map.put("checkinDays", days);

        DateTime hiredate = DateUtil.parse(userService.searchUserHiredate(userId));
        DateTime startDate = DateUtil.beginOfWeek(DateUtil.date());
        //如果这一周比入职日期早，把入职时间当作一周的最开始，不然入职之前就已经算请假了
        if(startDate.isBefore(hiredate)){
            startDate = hiredate;
        }
        DateTime endDate = DateUtil.endOfWeek(DateUtil.date());
        HashMap param = new HashMap();
        param.put("startDate", startDate.toString());
        param.put("endDate", endDate.toString());
        param.put("userId", userId);
        //    /*根据传来的开始startime、结束日期endtime以及userid，查询开始到结束每天的签到情况->>>>>>返回日期date和状态status（正常、迟到）*/
        ArrayList<HashMap> list = checkinService.searchWeekCheckin(param);
        //map放进一周的考勤情况
        map.put("weekCheckin", list);
        return R.ok().put("result", map);
    }


    /** 8-13实现我的考勤页面（业务层&持久层）(20-54)
     * 前端传来表单（月份，年份），token
     * token解密成userid，查找员工入职日期
     * 注意入职日期VS开始的前端传进来的年月*/
    @PostMapping("/searchMonthCheckin")
    @ApiOperation("查询用户某月签到数据")
    public R searchMonthCheckin(@Valid @RequestBody SearchMonthCheckinForm form, @RequestHeader("token") String token){
        int userId=jwtUtil生成解密验证TOKEN.getUserId(token);
        DateTime hiredate=DateUtil.parse(userService.searchUserHiredate(userId));
        String month=form.getMonth()<10?"0"+form.getMonth():form.getMonth().toString();
        DateTime startDate=DateUtil.parse(form.getYear()+"-"+month+"-01");
       /** //传进来的开始年月比入职日期的那个年月早，抛异常（早了几个月）*/
        if(startDate.isBefore(DateUtil.beginOfMonth(hiredate))){
            throw new EmosException("只能查询考勤之后日期的数据");
        }
/**
        //传进来的开始年月没有入职日期的那个年月早，但是可能在同一个月里面，开始日期比入职日期早（同一个月里面，但是早了几个天）
*/
        if(startDate.isBefore(hiredate)){
            startDate=hiredate;
        }
        DateTime endDate=DateUtil.endOfMonth(startDate);
        HashMap param=new HashMap();
        param.put("userId",userId);
        param.put("startDate",startDate.toString());
        param.put("endDate",endDate.toString());
        //返回日期date和状态status（正常、迟到）
        ArrayList<HashMap> list=checkinService.searchMonthCheckin(param);
        int sum_1=0,sum_2=0,sum_3=0;
        for(HashMap<String,String> one:list){
            String type=one.get("type");
            String status=one.get("status");
            if("工作日".equals(type)){
                if("正常".equals(status)){
                    sum_1++;
                }
                else if("迟到".equals(status)){
                    sum_2++;
                }
                else if("缺勤".equals(status)){
                    sum_3++;
                }
            }
        }
        return R.ok().put("list",list).put("sum_1",sum_1).put("sum_2",sum_2).put("sum_3",sum_3);
    }
}